package com.yanqu.road.utils;

import java.util.*;

public class ListHelper {
    /**
     * 数值数组比较，忽略顺序
     */
    public static boolean integerListCompare(List<Integer> list1, List<Integer> list2){
        if(null == list1 || null == list2){
            return false;
        }
        if(list1.size() != list2.size()){
            return false;
        }
        List<Integer> tempList = new ArrayList<>(list2);
        for(Integer value : list1){
            if(!tempList.contains(value)){
                return false;
            }
            tempList.remove(value);
        }
        return true;
    }

    /**
     * 切割，每个子List分为M个元素，M为参数，多余元素分在最后一个字数组
     * @param originalList 原数组
     * @param elementsPerPartition 每个子LIST元素数量
     * @return
     * @param <T>
     */
    public static <T> List<List<T>> partitionList(List<T> originalList, int elementsPerPartition) {
        List<List<T>> partitions = new ArrayList<>();
        if (elementsPerPartition <= 0) {
            return partitions;
        }

        for (int start = 0; start < originalList.size(); start += elementsPerPartition) {
            int end = Math.min(start + elementsPerPartition, originalList.size());
            partitions.add(new ArrayList<>(originalList.subList(start, end)));
        }

        return partitions;
    }

    /**
     * 分页
     * @param list
     * @param pageSize
     * @param pageNo
     * @return
     * @param <T>
     */
    public static <T> List<T> paginate(List<T> list, int pageSize, int pageNo) {
        int startIndex = (pageNo - 1) * pageSize;
        int endIndex = Math.min(startIndex + pageSize, list.size());
        if (startIndex >= list.size()) {
            return new ArrayList<>();
        }
        return list.subList(startIndex, endIndex);
    }

    /**
     * 从给定的列表中随机选择N个不重复的元素。
     *
     * @param objects 输入的列表
     * @param n       要选择的元素数量
     * @param <T>     泛型类型
     * @return 包含n个随机元素的新列表，如果n大于输入列表长度，返回整个列表
     */
    public static <T> List<T> getRandomSubList(List<T> objects, int n) {
        if (n > objects.size()) {
            return new ArrayList<>(objects);
        }

        Random rand = new Random();
        List<T> result = new ArrayList<>(n);

        while (result.size() < n) {
            int randomIndex = rand.nextInt(objects.size());
            if (!result.contains(objects.get(randomIndex))) {
                result.add(objects.get(randomIndex));
            }
        }

        return result;
    }

    /**
     * 从列表中随机获取一个元素。
     *
     * @param list 目标列表
     * @return 列表中的一个随机元素，如果列表为空则返回null
     */
    public static <T> T getRandomElement(List<T> list) {
        if (list != null && !list.isEmpty()) {
            Random random = new Random();
            int randomIndex = random.nextInt(list.size());
            return list.get(randomIndex);
        }
        return null;
    }

    /**
     * 获取列表中的前N个元素，按照指定的比较器进行排序。获取TOP N元素
     * @param <T> The type of the objects in the list.
     * @param list The list to be sorted.
     * @param comparator The comparator used to sort the list.
     * @param limit The number of top elements to return.
     * @return A new list containing the top 'limit' elements, or the original list if it has fewer than 'limit' elements.
     */
    public static <T> List<T> getTopElementsByComparator(List<T> list, Comparator<T> comparator, int limit) {
        // Check if the list is null or empty
        if (list == null || list.isEmpty()) {
            return list;
        }
        // Sort the list using the provided comparator
        Collections.sort(list, comparator);
        // Return the top 'limit' elements
        return list.subList(0, Math.min(limit, list.size()));
    }

    /**
     * 获取列表中指定排名范围内的元素，不包含排名。
     *
     * @param list   列表
     * @param index   排名index
     * @param start  前几个
     * @param end    后几个
     * @param <T>    泛型类型
     * @return 包含指定排名范围内的元素的新列表
     */
    public static <T> List<T> getSubListWithoutIndex(List<T> list, int index, int start, int end) {
        List<T> extractedList = new ArrayList<>();

        // Calculate the start and end bounds
        int startIndex = Math.max(0, index - start);
        int endIndex = Math.min(list.size(), index + end + 1); // +1 because end is inclusive

        // Add elements from the calculated range, skipping the element at 'index'
        for (int i = startIndex; i < endIndex; i++) {
            if (i != index) {
                extractedList.add(list.get(i));
            }
        }

        return extractedList;
    }

    /**
     * 获取LIST中位元素
     * @param list
     * @return
     * @param <T>
     */
    public static <T> T getMedian(List<T> list) {
        int size = list.size();
        int index = size / 2;
        if (size % 2 == 0) {
            return list.get(index - 1);
        } else {
            return list.get(index);
        }
    }
}
